home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / fs / ext2 / symlink.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  2.4 KB  |  125 lines

  1. /*
  2.  *  linux/fs/ext2/symlink.c
  3.  *
  4.  *  Copyright (C) 1992, 1993  Remy Card (card@masi.ibp.fr)
  5.  *
  6.  *  from
  7.  *
  8.  *  linux/fs/minix/symlink.c
  9.  *
  10.  *  Copyright (C) 1991, 1992  Linus Torvalds
  11.  *
  12.  *  ext2 symlink handling code
  13.  */
  14.  
  15. #include <asm/segment.h>
  16.  
  17. #include <linux/errno.h>
  18. #include <linux/fs.h>
  19. #include <linux/ext2_fs.h>
  20. #include <linux/sched.h>
  21. #include <linux/stat.h>
  22.  
  23. static int ext2_readlink (struct inode *, char *, int);
  24. static int ext2_follow_link (struct inode *, struct inode *, int, int,
  25.                    struct inode **);
  26.  
  27. /*
  28.  * symlinks can't do much...
  29.  */
  30. struct inode_operations ext2_symlink_inode_operations = {
  31.     NULL,            /* no file-operations */
  32.     NULL,            /* create */
  33.     NULL,            /* lookup */
  34.     NULL,            /* link */
  35.     NULL,            /* unlink */
  36.     NULL,            /* symlink */
  37.     NULL,            /* mkdir */
  38.     NULL,            /* rmdir */
  39.     NULL,            /* mknod */
  40.     NULL,            /* rename */
  41.     ext2_readlink,        /* readlink */
  42.     ext2_follow_link,    /* follow_link */
  43.     NULL,            /* bmap */
  44.     NULL,            /* truncate */
  45.     NULL            /* permission */
  46. };
  47.  
  48. static int ext2_follow_link(struct inode * dir, struct inode * inode,
  49.                 int flag, int mode, struct inode ** res_inode)
  50. {
  51.     int error;
  52.     struct buffer_head * bh = NULL;
  53.     char * link;
  54.  
  55.     *res_inode = NULL;
  56.     if (!dir) {
  57.         dir = current->root;
  58.         dir->i_count++;
  59.     }
  60.     if (!inode) {
  61.         iput (dir);
  62.         return -ENOENT;
  63.     }
  64.     if (!S_ISLNK(inode->i_mode)) {
  65.         iput (dir);
  66.         *res_inode = inode;
  67.         return 0;
  68.     }
  69.     if (current->link_count > 5) {
  70.         iput (dir);
  71.         iput (inode);
  72.         return -ELOOP;
  73.     }
  74.     if (inode->i_blocks) {
  75.         if (!(bh = ext2_bread (inode, 0, 0, &error))) {
  76.             iput (dir);
  77.             iput (inode);
  78.             return -EIO;
  79.         }
  80.         link = bh->b_data;
  81.     } else
  82.         link = (char *) inode->u.ext2_i.i_data;
  83.     current->link_count++;
  84.     error = open_namei (link, flag, mode, res_inode, dir);
  85.     current->link_count--;
  86.     iput (inode);
  87.     if (bh)
  88.         brelse (bh);
  89.     return error;
  90. }
  91.  
  92. static int ext2_readlink (struct inode * inode, char * buffer, int buflen)
  93. {
  94.     struct buffer_head * bh = NULL;
  95.     char * link;
  96.     int i, err;
  97.     char c;
  98.  
  99.     if (!S_ISLNK(inode->i_mode)) {
  100.         iput (inode);
  101.         return -EINVAL;
  102.     }
  103.     if (buflen > inode->i_sb->s_blocksize - 1)
  104.         buflen = inode->i_sb->s_blocksize - 1;
  105.     if (inode->i_blocks) {
  106.         bh = ext2_bread (inode, 0, 0, &err);
  107.         if (!bh) {
  108.             iput (inode);
  109.             return 0;
  110.         }
  111.         link = bh->b_data;
  112.     }
  113.     else
  114.         link = (char *) inode->u.ext2_i.i_data;
  115.     i = 0;
  116.     while (i < buflen && (c = link[i])) {
  117.         i++;
  118.         put_fs_byte (c, buffer++);
  119.     }
  120.     iput (inode);
  121.     if (bh)
  122.         brelse (bh);
  123.     return i;
  124. }
  125.